package com.lf2.tool;

import com.lf2.Lf_Debug;

import java.util.ArrayList;
import java.util.List;


public class BytesUtil
{
	private static int DEBUG_LEVEL = Lf_Debug.DEBUG_TOOL;
    public BytesUtil() {}

    public static String getStrings(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02x",  bytes[i]));
        }
        return sb.toString();
    }

    public static String getStrings(byte sbyte)
    {
        byte[] bytes = new byte[1];
        for (int i = 0; i < 1; i++) {
            bytes[i] = ((byte)(sbyte & 0xFF));
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02x",  bytes[i]));
        }
        return sb.toString();
    }

    public static byte[] fill(byte[] srcBytes, byte value)
    {
    	byte[] bytes = new byte[srcBytes.length];
    	for(int i=0; i<srcBytes.length; i++)
    	{
    		bytes[i] = value;
    	}
    	return bytes;
    }

    public static byte[] fill(byte[] srcBytes, char value)
    {
    	byte[] bytes = new byte[srcBytes.length];
    	for(int i=0; i<srcBytes.length; i++)
    	{
    		bytes[i] = (byte)(value&0xff);
    	}
    	return bytes;
    }

    public static byte[] fill(byte[] srcBytes, int value)
    {
    	byte[] bytes = new byte[srcBytes.length];
    	for(int i=0; i<srcBytes.length; i++)
    	{
    		bytes[i] = (byte)(value&0xff);
    	}
    	return bytes;
    }

    public static byte[] clr2blankByte(byte[] srcBytes)
    {
    	byte[] bytes;
    	int i;
    	for(i=0; i<srcBytes.length; i++)
    	{
    		if(srcBytes[i] == 0x00)
    		{
    			srcBytes[i] = 0x20;
    		}
    	}
    	bytes = new byte[i];
    	System.arraycopy(srcBytes, 0, bytes, 0, i);
    	return bytes;
    }

    public static byte[] clrblankByte(byte[] srcBytes)
    {
    	byte[] bytes;
    	int i;
    	for(i=0; i<srcBytes.length; i++)
    	{
    		if(srcBytes[i] == 0x20)
    		{
    			break;
    		}
    	}
    	bytes = new byte[i];
    	System.arraycopy(srcBytes, 0, bytes, 0, i);
    	return bytes;
    }

    public static byte[] clearblankByte(char[] srcBytes)
    {
    	byte[] bytes;
    	byte[] btmp = new byte[srcBytes.length];
    	int i;
    	for(i=0; i<srcBytes.length; i++)
    	{
    		if(srcBytes[i] == 0x00)
    		{
    			break;
    		}
    		btmp[i] = (byte)srcBytes[i];
    	}
    	bytes = new byte[i];
    	System.arraycopy(btmp, 0, bytes, 0, i);
    	return bytes;
    }

    public static byte[] clearblankByte(byte[] srcBytes)
    {
    	byte[] bytes;
    	int i;
    	for(i=0; i<srcBytes.length; i++)
    	{
    		if(srcBytes[i] == 0x00)
    		{
    			break;
    		}
    	}
    	bytes = new byte[i];
    	System.arraycopy(srcBytes, 0, bytes, 0, i);
    	return bytes;
    }

    public static byte[] subByte(byte[] srcBytes, int offset, int len)
    {
        byte[] bytes;
        if (srcBytes == null) {
            return null;
        }

        if ((len > srcBytes.length) || (offset + len > srcBytes.length) ||
            (offset >= srcBytes.length)) {
            return null;
        }

        if (len == -1) {
            bytes = new byte[srcBytes.length - offset];
            System.arraycopy(srcBytes, offset, bytes, 0, srcBytes.length - offset);
        }
        else {
            bytes = new byte[len];
            System.arraycopy(srcBytes, offset, bytes, 0, len);
        }
        Lf_Debug.dbg_mPrintfWHex(Lf_Debug._FILE_LINE_FUNC_(DEBUG_LEVEL), bytes, bytes.length, "data");
        return bytes;
    }

    public static byte[] mergeBytes(byte[] bytesA, byte[] bytesB)
    {
        if ((bytesA == null) || (bytesA.length == 0))
            return bytesB;
        if ((bytesB == null) || (bytesB.length == 0)) {
            return bytesA;
        }

        byte[] bytes = new byte[bytesA.length + bytesB.length];

        System.arraycopy(bytesA, 0, bytes, 0, bytesA.length);
        System.arraycopy(bytesB, 0, bytes, bytesA.length, bytesB.length);

        return bytes;
    }

    public static byte[] merge(byte[]... data)
    {
        if (data == null) {
            return null;
        }
        byte[] bytes = null;
        for (int i = 0; i < data.length; i++) {
            bytes = mergeBytes(bytes, data[i]);
        }
        return bytes;
    }

    public static int bytecmp(byte[] hex1, byte[] hex2, int len)
    {
        for (int i = 0; i < len; i++) {
            if (hex1[i] != hex2[i]) {
                return 1;
            }
        }

        return 0;
    }

    public static int bytecmp(char[] hex1, char[] hex2, int len)
    {
        for (int i = 0; i < len; i++) {
            if (hex1[i] != hex2[i]) {
                return 1;
            }
        }

        return 0;
    }

    public static byte[] hexString2ByteArray(String hexStr)
    {
        if (hexStr == null)
            return null;
        if (hexStr.length() % 2 != 0) {
            hexStr = hexStr + "0";
        }
        byte[] data = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            char hc = hexStr.charAt(2 * i);
            char lc = hexStr.charAt(2 * i + 1);
            byte hb = hexChar2Byte(hc);
            byte lb = hexChar2Byte(lc);
            if ((hb < 0) || (lb < 0)) {
                return null;
            }
            int n = hb << 4;
            data[i] = ((byte)(n + lb));
        }
        return data;
    }

    public static byte hexChar2Byte(char c) {
        if ((c >= '0') && (c <= '9'))
        	return (byte)(c - '0');
        if ((c >= 'a') && (c <= 'f'))
        	return (byte)(c - 'a' + 10);
        if ((c >= 'A') && (c <= 'F'))
        	return (byte)(c - 'A' + 10);
        return -1;
    }

    public static String byteArray2HexString(byte[] arr, int len)
    {
    	int temp;
        StringBuilder sb = new StringBuilder();
        if(len<arr.length)
        {
        	temp=len;
        }
        else
        {
        	temp=arr.length;
        }
        for (int i = 0; i < temp; i++) {
            sb.append(String.format("%02x", new Object[] { Byte.valueOf(arr[i]) }).toUpperCase());
        }
        return sb.toString();
    }

    public static String byteArray2HexString(byte[] arr)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            sb.append(String.format("%02x",  Byte.valueOf(arr[i])).toUpperCase());
        }
        return sb.toString();
    }

    public static String byteArray2HexString(List<Byte> arrList) {
        byte[] arr = new byte[arrList.size()];
        for (int i = 0; i < arrList.size(); i++) {
            arr[i] = ((Byte)arrList.get(i)).byteValue();
        }
        return byteArray2HexString(arr);
    }

    public static String byteArray2HexStringWithSpace(byte[] arr) {
        StringBuilder sbd = new StringBuilder();
        byte[] arrayOfByte = arr;
        int j = arr.length;
        for (int i = 0; i < j; i++) {
            byte b = arrayOfByte[i];
            String tmp = Integer.toHexString(0xFF & b);
            if (tmp.length() < 2)
                tmp = "0" + tmp;
            sbd.append(tmp);
            sbd.append(" ");
        }
        return sbd.toString();
    }

    public static String getBCDString(byte[] data, int start, int end) {
        byte[] t = new byte[end - start + 1];
        System.arraycopy(data, start, t, 0, t.length);
        return byteArray2HexString(t);
    }

    public static String getHexString(byte[] data, int start, int end) {
        byte[] t = new byte[end - start + 1];
        System.arraycopy(data, start, t, 0, t.length);
        return byteArray2HexStringWithSpace(t);
    }

    public static byte[] toByteArray(int source, int len)
    {
        byte[] bLocalArr = new byte[len];
        for (int i = 0; (i < 4) && (i < len); i++) {
            bLocalArr[(len - 1 - i)] = ((byte)(source >> 8 * i & 0xFF));
        }
        return bLocalArr;
    }

    public static byte[] BCD_To_Hex(byte[] bcd, int bcd_len)
    {
        byte[] ascii = new byte[bcd_len];
        int j = 0;
        for (int i = 0; i < bcd_len; i++) {
        	ascii[i] = (byte)(((bcd[j])/10)<<4);
        	ascii[i] += bcd[j]%10;
            j++;
        }
        return ascii;
    }

    public static byte[] Hex_To_BCD(byte[] ascii, int asc_len)
    {
        byte[] bcd = new byte[asc_len];
        int j = 0;
        for (int i = 0; i < asc_len; i++) {
        	bcd[i] = (byte)(((ascii[j]&0xf0)>>4)*10);
        	bcd[i] += ascii[j]&0x0f;
            j++;
        }
        return bcd;
    }

    public static byte[] Hex2String(byte[] hex, int hex_len)
    {
        byte[] bcd = new byte[hex_len*2];

        for (int i = 0; i < hex_len; i++) {
            bcd[2*i] = (byte) (((hex[i] & 0xf0)>>4)+'0');
            bcd[2*i+1] = (byte) ((hex[i] & 0x0f)+'0');
        }
        return bcd;
    }


    public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len)
    {
        byte[] bcd = new byte[(asc_len+1) / 2];
        int j = 0;
        for (int i = 0; i < (asc_len + 1) / 2; i++) {
            bcd[i] = asc_to_bcd(ascii[(j++)]);
            bcd[i] = ((byte)((j >= asc_len ? 0 : asc_to_bcd(ascii[(j++)])) + (bcd[i] << 4)));
        }
        return bcd;
    }

    private static byte asc_to_bcd(byte asc) {
        byte bcd;
        if ((asc >= 48) && (asc <= 57))
        {
            bcd = (byte)(asc - 48);
        }
        else
        {
            if ((asc >= 65) && (asc <= 70))
            {
                bcd = (byte)(asc - 65 + 10);
            }
            else
            {
                if ((asc >= 97) && (asc <= 102))
                {
                    bcd = (byte)(asc - 97 + 10);
                }
                else
                {
                    bcd = (byte)(asc - 48);
                }
            }
        }
        return bcd;
    }

    public static boolean[] getBooleanArray(byte b)
    {
        boolean[] array = new boolean[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = ((b & 0x1) == 1 ? true : false);
            b = (byte)(b >> 1);
        }
        return array;
    }

    public static int booleanArray2i(boolean[] b) {
        int res = 0;
        int len = b.length;
        for (int i = 0; i < len; i++)
        {
            if (b[i] != false) {
                res += (int) Math.pow(2.0D, len - i - 1);
            }
        }
        return res;
    }

    public static int byte2Int(byte[] b) {
        int temp = 0;
        for (int i = 0; i < b.length; i++)
        {
            temp += ((b[i] & 0xFF) << 8 * (b.length - i - 1));
        }
        return temp;
    }

    public static int byte2Int(byte[] b, int bytesNum) {
        int intValue = 0;
        for (int i = 0; i < b.length; i++) {
            intValue += ((b[i] & 0xFF) << 8 * (bytesNum - 1 - i));
        }
        return intValue;
    }

    public static byte[] int2Bytes(int length, int bytesNum) {
        if (bytesNum > 4)
        {
            bytesNum = 4;
        }
        else if (bytesNum <= 0)
        {
            bytesNum = 1;
        }

        if (bytesNum == 4)
            return new byte[] { (byte)(length >> 24 & 0xFF), (byte)(length >> 16 & 0xFF), (byte)(length >> 8 & 0xFF), (byte)(length & 0xFF) };
        if (bytesNum == 3)
            return new byte[] { (byte)(length >> 16 & 0xFF), (byte)(length >> 8 & 0xFF), (byte)(length & 0xFF) };
        if (bytesNum == 2) {
            return new byte[] { (byte)(length >> 8 & 0xFF), (byte)(length & 0xFF) };
        }
        return new byte[] { (byte)(length & 0xFF) };
    }

    public static String asc2Bcd(String str)
    {
        byte[] bcd = ASCII_To_BCD(str.getBytes(), str.length());
        return bcd2Str(bcd);
    }

    private static String bcd2Str(byte[] bytes) {
        char[] temp = new char[bytes.length * 2];

        for (int i = 0; i < bytes.length; i++)
        {
            char val = (char)((bytes[i] & 0xF0) >> 4 & 0xF);
            temp[(i * 2)] = ((char)(val > '\t' ? val + 'A' - 10 : val + '0'));

            val = (char)(bytes[i] & 0xF);
            temp[(i * 2 + 1)] = ((char)(val > '\t' ? val + 'A' - 10 : val + '0'));
        }
        return new String(temp);
    }

    public static byte[] hex2byte(String str)
    {
        int len = str.length();
        String stmp = null;
        byte[] bt = new byte[len / 2];
        for (int n = 0; n < len / 2; n++) {
            stmp = str.substring(n * 2, n * 2 + 2);
            bt[n] = ((byte) Integer.parseInt(stmp, 16));
        }
        return bt;
    }

    public static String byte2hex(byte[] b)
    {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++)
        {
            stmp = Integer.toHexString(b[n] & 0xFF);
            if (stmp.length() == 1)
            {
                hs = hs + "0" + stmp;
            }
            else
            {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    public static List<Byte> hexString2ByteList(String dataStr)
    {
        byte[] dataArray = hexString2ByteArray(dataStr);
        List<Byte> result = new ArrayList<Byte>();
        for (int i = 0; i < dataArray.length; i++) {
            result.add(Byte.valueOf(dataArray[i]));
        }
        return result;
    }

    public static boolean isBitSet(byte val, int bitPos)
    {
        if ((bitPos < 1) || (bitPos > 8)) {
            throw new IllegalArgumentException("parameter 'bitPos' must be between 1 and 8. bitPos=" + bitPos);
        }
        if ((val >> bitPos - 1 & 0x1) == 1) {
            return true;
        }
        return false;
    }

    public static boolean isAsciiByte(byte[] srcBytes)
    {
    	for(int i=0; i<srcBytes.length; i++)
		{
			if((srcBytes[i] >= '0'&& srcBytes[i] <= '9')
			   ||(srcBytes[i] >= 'A' && srcBytes[i] <= 'Z')
			   ||(srcBytes[i] >= 'a' && srcBytes[i] <= 'z'))
			{

			}
			else
			{
				return false;
			}
		}
    	return true;
    }

    public static byte[] makeDistanceBytes(int distance)
    {
        int fiveKm = 0;
        int fourKm = 0;
        int threeKm = 0;
        int twoKm = 0;
        int oneKm = 0;
        int halfOfOneKm = 0;

        fiveKm = distance / 5000;
        distance -= 5000 * fiveKm;

        fourKm = distance / 4000;
        distance -= 4000 * fourKm;

        threeKm = distance / 3000;
        distance -= 3000 * threeKm;

        twoKm = distance / 2000;
        distance -= 2000 * twoKm;

        oneKm = distance / 1000;
        distance -= 1000 * oneKm;

        if (distance != 0) {
            halfOfOneKm = 1;
        }

        byte[] distanceBytes = new byte[fiveKm + fourKm + threeKm + twoKm + oneKm + halfOfOneKm];
        int k = 0;
        if (fiveKm > 0) {
            for (int i = 0; i < fiveKm; i++) {
                distanceBytes[(k++)] = 5;
            }
        }

        if (fourKm > 0) {
            for (int i = 0; i < fourKm; i++) {
                distanceBytes[(k++)] = 4;
            }
        }

        if (threeKm > 0) {
            for (int i = 0; i < threeKm; i++) {
                distanceBytes[(k++)] = 3;
            }
        }

        if (twoKm > 0) {
            for (int i = 0; i < twoKm; i++) {
                distanceBytes[(k++)] = 2;
            }
        }

        if (oneKm > 0) {
            for (int i = 0; i < oneKm; i++) {
                distanceBytes[(k++)] = 1;
            }
        }

        if (halfOfOneKm > 0) {
            for (int i = 0; i < halfOfOneKm; i++) {
                distanceBytes[(k++)] = 0;
            }
        }

        return distanceBytes;
    }

    public static int getDistanceFromBytes(byte[] addBytes)
    {
        if ((addBytes == null) || (addBytes.length == 0)) {
            return 0;
        }

        int km = 0;
        for (int i = 0; i < addBytes.length; i++) {
            if ((addBytes[i] & 0xFF) == 0) {
                km += 500;
            }
            else if ((addBytes[i] & 0xFF) == 1) {
                km += 1000;
            }
            else if ((addBytes[i] & 0xFF) == 2) {
                km += 2000;
            }
            else if ((addBytes[i] & 0xFF) == 3) {
                km += 3000;
            }
            else if ((addBytes[i] & 0xFF) == 4) {
                km += 4000;
            }
            else if ((addBytes[i] & 0xFF) == 5) {
                km += 5000;
            }
        }

        return km;
    }
}

